package com.study.algorithm.datastruct.tree.impl;

import com.study.algorithm.datastruct.tree.AVlTreeOperate;
import com.study.algorithm.datastruct.tree.BinaryTreeOperate;
import com.study.algorithm.datastruct.tree.BinaryTreeTravel;
import com.study.algorithm.datastruct.tree.model.AVLTree;
import com.study.algorithm.datastruct.tree.model.BinaryTree;

import java.util.List;

public class BinaryTreeOperateImpl implements BinaryTreeOperate {

    private BinaryTreeTravel binaryTreeTravel;
    private AVlTreeOperate balanceBinaryTreeOperate;

    @Override
    public BinaryTree buildBinaryTreeTroughIntegerList(List<Integer> integers) {
        if (integers == null || integers.size() == 0) {
            return null;
        }
        int size = integers.size();
        BinaryTree tree = new BinaryTree();
        tree.setWeight(integers.get(0));
        for (int index = 1; index < size; index++) {
            buildChildNode(tree, integers.get(index));
        }
        return tree;
    }

    @Override
    public boolean isCompleteBinaryTree(BinaryTree binaryTree) {
        //todo:完全二叉树判断
        return false;
    }


    @Override
    public List<BinaryTree> getPreTravelTrace(BinaryTree binaryTree) {
        return getBinaryTreeTravel().getPreTravelTrace(binaryTree);
    }

    @Override
    public List<BinaryTree> getMiddleTravelTrace(BinaryTree binaryTree) {
        return getBinaryTreeTravel().getMiddleTravelTrace(binaryTree);
    }

    @Override
    public List<BinaryTree> getAfterTravelTrace(BinaryTree binaryTree) {

        return getBinaryTreeTravel().getAfterTravelTrace(binaryTree);
    }

    @Override
    public List<BinaryTree> getLevelTravelTrace(BinaryTree tree) {

        return getBinaryTreeTravel().getLevelTravelTrace(tree);
    }


    @Override
    public boolean isBalanceBinaryTree(BinaryTree binaryTree) {
        return getBalanceBinaryTreeOperate().isBalanceBinaryTree(binaryTree);
    }

    @Override
    public AVLTree buildBalanceBinaryTreeTroughWeight(List<Integer> integers) {
        return getBalanceBinaryTreeOperate().buildBalanceBinaryTreeTroughWeight(integers);
    }

    @Override
    public AVLTree insertAVLTreeNodeThroughWeight(AVLTree rootNode, int insertData) {
        return getBalanceBinaryTreeOperate().insertAVLTreeNodeThroughWeight(rootNode, insertData);

    }

    @Override
    public AVLTree removeAVLTreeNodeThroughWeight(AVLTree rootNode, int weight) {
        return getBalanceBinaryTreeOperate().insertAVLTreeNodeThroughWeight(rootNode, weight);
    }

    private void buildChildNode(BinaryTree treeNode, int data) {
        if (treeNode.getWeight() > data) {
            if (treeNode.hasLeftChildNode()) {
                buildChildNode(treeNode.getLeftChildNode(), data);
                return;
            }
            BinaryTree treeNode1 = new BinaryTree();
            treeNode1.setWeight(data);
            treeNode.setLeftChildNode(treeNode1);
            return;
        }

        if (treeNode.hasRightChildNode()) {
            buildChildNode(treeNode.getRightChildNode(), data);
            return;
        }
        BinaryTree treeNode1 = new BinaryTree();
        treeNode1.setWeight(data);
        treeNode.setRightChildNode(treeNode1);
    }

    private void initBinaryTreeTravel() {
        if (binaryTreeTravel == null) {
            synchronized (this) {
                if (binaryTreeTravel == null) {
                    binaryTreeTravel = BinaryTreeTravelImpl.getInstance();
                }
            }
        }
    }

    private void initBalanceBinaryTree() {
        if (balanceBinaryTreeOperate == null) {
            synchronized (this) {
                if (balanceBinaryTreeOperate == null) {
                    balanceBinaryTreeOperate = AVlTreeOperateImpl.getInstance();
                }
            }
        }
    }

    private BinaryTreeTravel getBinaryTreeTravel() {
        if (binaryTreeTravel == null) {
            initBinaryTreeTravel();
        }
        return binaryTreeTravel;
    }

    private AVlTreeOperate getBalanceBinaryTreeOperate() {
        if (balanceBinaryTreeOperate == null) {
            initBalanceBinaryTree();
        }
        return balanceBinaryTreeOperate;
    }
}
